package cn.yanceysong.scene.s1_s10.设计购物车;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;

import java.util.ArrayList;
import java.util.List;

public class GoodsCar {
    /**
     * .场景题:设计购物车功能
     * .
     * .需求分析:
     * .1. 支持已登录和未登录用户的购物车
     * .2. 支持添加商品到购物车(加购)
     * .3. 支持修改购物车商品数量
     * .4. 支持删除购物车商品
     * .5. 支持查看购物车商品列表
     * .6. 支持清空购物车
     * .7. 需要记录商品SKUID、数量、加购时间
     * .
     * .思考方式:
     * .1. 未登录用户购物车:
     * .   - 存储在客户端(Cookie/LocalStorage)
     * .   - 无需后端持久化,本场景不实现
     * .
     * .2. 已登录用户购物车:
     * .   - 需要后端持久化存储
     * .   - 支持跨设备同步
     * .   - 需要高性能读写
     * .
     * .3. 存储内容设计:
     * .   - SKUID: 商品唯一标识
     * .   - count: 商品数量
     * .   - timestamp: 加购时间
     * .   - 商品详情(价格、库存等)实时查询,不存储
     * .
     * .解题思路:
     * .1. 数据结构选择 - 为什么用Redis Hash?
     * .   - 一个用户对应一个购物车
     * .   - 一个购物车包含多个商品
     * .   - 需要按SKU维度增删改查
     * .   - Hash结构天然适合这种场景
     * .
     * .2. Redis Key设计:
     * .   Key: "cart:" + userId  (如: "cart:user123")
     * .   Field: skuId           (如: "sku10086")
     * .   Value: JSON字符串      (如: {"count":2,"timestamp":1700000000})
     * .
     * .3. 数据结构示意图:
     * .   Redis Key: "cart:user123"
     * .   +-------------+----------------------------------+
     * .   |    Field    |              Value               |
     * .   +-------------+----------------------------------+
     * .   | "sku10086"  | {"count":2,"timestamp":1001}     |
     * .   | "sku10010"  | {"count":5,"timestamp":1002}     |
     * .   | "sku10099"  | {"count":1,"timestamp":1003}     |
     * .   +-------------+----------------------------------+
     * .
     * .实现的数据结构:
     * .- Redis Hash (哈希表)
     * .  优点:
     * .  1. 按商品维度增删改查,O(1)时间复杂度
     * .  2. 支持批量获取所有商品
     * .  3. 内存占用相对优化
     * .  4. 天然支持购物车场景的业务模型
     * .
     * .时间复杂度:
     * .- 添加商品: O(1)
     * .- 更新数量: O(1)
     * .- 删除商品: O(1)
     * .- 查询购物车: O(N) - N为商品数量
     * .- 清空购物车: O(1)
     * .
     * .空间复杂度: O(N) - N为购物车商品数量
     */
    @AllArgsConstructor
    public static class ShoppingCartService {
        private RedissonClient redissonClient;

        private static final String CART_PREFIX = "cart:";

        /**
         * .添加商品到购物车
         * .
         * .@param userId 用户ID
         * .@param skuId 商品SKU ID
         * .@param count 商品数量
         */
        public void addToCart(String userId, String skuId, int count) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);

            CartItem item = cart.get(skuId);
            if (item != null) {
                // 商品已存在,累加数量
                item.setCount(item.getCount() + count);
                item.setTimestamp(System.currentTimeMillis());
            } else {
                // 新商品,创建记录
                item = new CartItem(skuId, count, System.currentTimeMillis());
            }
            cart.put(skuId, item);
        }

        /**
         * .更新商品数量
         */
        public boolean updateCount(String userId, String skuId, int count) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);

            CartItem item = cart.get(skuId);
            if (item == null) {
                return false;
            }

            if (count <= 0) {
                cart.remove(skuId);
            } else {
                item.setCount(count);
                item.setTimestamp(System.currentTimeMillis());
                cart.put(skuId, item);
            }
            return true;
        }

        /**
         * .删除购物车商品
         */
        public boolean removeFromCart(String userId, String skuId) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);
            return cart.remove(skuId) != null;
        }

        /**
         * .获取购物车列表
         */
        public List<CartItem> getCartItems(String userId) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);
            return new ArrayList<>(cart.values());
        }

        /**
         * .获取购物车商品数量
         */
        public int getCartSize(String userId) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);
            return cart.size();
        }

        /**
         * .清空购物车
         */
        public void clearCart(String userId) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);
            cart.clear();
        }

        /**
         * .检查商品是否在购物车中
         */
        public boolean containsItem(String userId, String skuId) {
            String key = CART_PREFIX + userId;
            RMap<String, CartItem> cart = redissonClient.getMap(key);
            return cart.containsKey(skuId);
        }

        /**
         * .购物车商品实体类
         */
        @Data
        public static class CartItem {
            private String skuId;
            private int count;
            private long timestamp;

            public CartItem(String skuId, int count, long timestamp) {
                this.skuId = skuId;
                this.count = count;
                this.timestamp = timestamp;
            }

            @Override
            public String toString() {
                return "CartItem{skuId='" + skuId + "', count=" + count + ", timestamp=" + timestamp + "}";
            }
        }
    }
}
